﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace AlgebraCodeFunction
{
    public class Program
    {
        static void Main(string[] args)
        {
            //var vvv = Condition.Compare("a+(b+c)", "a+b+c");

            OrderGlobal orderGlobal = new OrderGlobal();
            orderGlobal.Init();
            orderGlobal.CompileType(@"
    //定义类型 G
    define_type G 
    define_type func G  //定义类型 func 为函数类型
    define_function_binaryOperator + 0 G G G func //定义双目表达式函数 + 优先级0，左运算参数类型为G 右运算参数类型为G 得出的结果类型为G 该函数类型属于上一行代码定义的func类型
    define_function_binaryOperator * 1 G G G func //定义双目表达式函数 * 优先级1
    define_function_binaryOperator ^ 2 G G G func //定义双目表达式函数 ^ 优先级2
            ");

            orderGlobal.CompileDomain(@"
    a+b=b+a //加法交换律
    a+(b+c)=>a+b+c //加法结合律
    a*b=b*a //乘法交换律
    a*(b*c)=>a*b*c //乘法结合律
    a*(b+c)=>a*b+a*c //加法乘法分配律
    a^(b+c)=>a^b*a^c //乘方加法分配律
            ");

            Function function = orderGlobal.Run("(a+b)*(c+d)*(e+d*fe)");

            Console.WriteLine(function);



            return;
            FunctionType any = new FunctionType("any");
            FunctionType varType = new FunctionType("variable", any);
            FunctionType demo1_FunctionType = new FunctionType("function", any);

            BinaryOperatorFunctionType add = new BinaryOperatorFunctionType("+", 0, any, any, any, demo1_FunctionType);
            BinaryOperatorFunctionType mult = new BinaryOperatorFunctionType("*", 1, any, any, any, demo1_FunctionType);
            BinaryOperatorFunctionType pow = new BinaryOperatorFunctionType("^", 2, any, any, any, demo1_FunctionType);

            FunctionType func2 = new FunctionType("func2", new List<FunctionType>() { any, any }, any, demo1_FunctionType);
            FunctionType func3 = new FunctionType("func3", new List<FunctionType>() { any, any, any }, any, demo1_FunctionType);

            InfixExpressionAnalysis analysis = new InfixExpressionAnalysis(varType);
            analysis.binaryOperatorFunctionTypes = new List<BinaryOperatorFunctionType>();
            analysis.binaryOperatorFunctionTypes.Add(add);
            analysis.binaryOperatorFunctionTypes.Add(mult);
            analysis.binaryOperatorFunctionTypes.Add(pow);

            analysis.functionTypes = new List<FunctionType>();
            analysis.functionTypes.Add(func2);
            analysis.functionTypes.Add(func3);

            var vc = analysis.StringToFunction("a+func2(a,func3(e+b,a,c*d+a)+d)");//a+(sin(k*cos(f+c))+c)
            analysis.StringToFunction("b+a");


            Function functionAdd1 = new Function(add);
            FunctionType demo1_a = new FunctionType("a", any);
            FunctionType demo1_b = new FunctionType("b", any);
            FunctionType demo1_c = new FunctionType("c", any);

            Function a = new Function("a", demo1_a);
            Function b = new Function("b", demo1_b);

            functionAdd1.SetArg(0, a);
            functionAdd1.SetArg(1, b);

            Function functionMult1 = new Function(mult);

            Function c = new Function("c", demo1_c);
            functionMult1.SetArg(0, functionAdd1);
            functionMult1.SetArg(1, c);
            var csv = functionMult1.ToString();
            Console.WriteLine();

            Console.ReadKey();

        }


    }


    public class GrammarAnalysisTree
    {
        public Function function;
        public Function algebraObject;
        public List<GrammarAnalysisTree> args = new List<GrammarAnalysisTree>();
        public override string ToString()
        {
            return algebraObject.ToString();
        }
    }

    /// <summary>
    /// 中缀表达式分析 此类将来可能会用第三方程序去替代
    /// 编写此类作为练习，是有意义的
    /// </summary>
    public class InfixExpressionAnalysis
    {
        public InfixExpressionAnalysis(FunctionType algebraType)
        {
            this.algebraType = algebraType;
        }

        public List<BinaryOperatorFunctionType> binaryOperatorFunctionTypes = new List<BinaryOperatorFunctionType>();
        public List<FunctionType> functionTypes = new List<FunctionType>();

        public FunctionType algebraType;

        /// <summary>
        /// 分析字符函数
        /// </summary>
        public class AnalysisCharsFunction : Function
        {
            public List<AnalysisChars> subs = new List<AnalysisChars>();

            public bool isString;
            public List<char> n;

            public AnalysisCharsFunction(string name, FunctionType functionType)
                : base(name, functionType)
            {
            }
            public AnalysisCharsFunction(FunctionType functionType)
                : base(functionType)
            {
            }
        }
        //brackets

        public class AnalysisChars
        {
            public enum AnalysisType
            {
                /// <summary>
                /// 未判断的
                /// </summary>
                nil,
                /// <summary>
                /// 字符
                /// </summary>
                Char,
                /// <summary>
                /// 变量名 已经被确定的字符
                /// </summary>
                Name,
                /// <summary>
                /// 二目表达式
                /// </summary>
                BinaryOperator,
                /// <summary>
                /// 函数
                /// </summary>
                Function,
            }
            public AnalysisType analysisType = AnalysisType.nil;

            public List<AnalysisChars> subs = new List<AnalysisChars>();

            public char n;
            public string functionName;
            public BinaryOperatorFunctionType binaryOperatorFunctionType;
            public FunctionType functionType;

            public string varName;

            public AnalysisChars()
            {

            }

            public AnalysisChars(char n)
            {
                this.n = n;
                analysisType = AnalysisType.Char;
            }

            public override string ToString()
            {
                StringBuilder sb = new StringBuilder();
                switch (analysisType)
                {
                    case AnalysisType.nil:
                        foreach (var item in subs)
                        {
                            if (item.analysisType == AnalysisType.Char)
                            {
                                sb.Append(item.n);
                            }
                            else
                            {
                                sb.Append(item.ToString());
                            }
                        }
                        return sb.ToString();

                    case AnalysisType.Char:
                        return n.ToString();
                    case AnalysisType.Name:
                        return varName;
                    case AnalysisType.BinaryOperator:

                        if (subs.Count > 1)
                        {
                            if (subs[0].analysisType == AnalysisType.BinaryOperator && subs[0].binaryOperatorFunctionType.priority < this.binaryOperatorFunctionType.priority)
                            {
                                sb.Append("(" + subs[0].ToString() + ")");
                            }
                            else
                            {
                                sb.Append(subs[0].ToString());
                            }
                            sb.Append(binaryOperatorFunctionType.typeName);
                            if (subs[1].analysisType == AnalysisType.BinaryOperator && subs[1].binaryOperatorFunctionType.priority < this.binaryOperatorFunctionType.priority)
                            {
                                sb.Append("(" + subs[1].ToString() + ")");
                            }
                            else
                            {
                                sb.Append(subs[1].ToString());
                            }
                            return sb.ToString();
                        }
                        return binaryOperatorFunctionType.typeName;
                    case AnalysisType.Function:
                        if (subs.Count > 0)
                        {
                            sb.Append(functionType.typeName + "(");
                            for (int i = 0; i < subs.Count - 1; i++)
                            {
                                sb.Append(subs[i] + ",");
                            }
                            sb.Append(subs[subs.Count - 1] + ")");
                            return sb.ToString();
                        }

                        return functionType.typeName;
                    default:
                        return "";
                }


                //if (isChar)
                //{
                //    return n.ToString();
                //}
                //StringBuilder sb = new StringBuilder();
                //foreach (var item in subs)
                //{
                //    if (item.isChar)
                //    {
                //        sb.Append(item.n);
                //    }
                //    else
                //    {
                //        sb.Append(item.ToString());
                //    }
                //}
                //return sb.ToString();
            }
        }

        /// <summary>
        /// 直接用字符串转换成函数，目前转换出错直接报错 需要修改
        /// 转换函数的函数类型需要预先设定
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public Function StringToFunction(string str)
        {
            //string str = "sin(cos(aee,cee*d,(a+b)*c),a)";//sin(cos(aee,cee),eee+(fee*gee))*aee + sin(aee,bee)    sin(aooo,boo)*coo+boo  sin(cos(aee,cee*d,(a+b)*c),a)
            List<char> chars = str.ToList();

            AnalysisChars analysisChars = new AnalysisChars();
            for (int i = 0; i < chars.Count; i++)
            {
                if (chars[i] != ' ')
                {
                    analysisChars.subs.Add(new AnalysisChars(chars[i]));
                }
            }
            bool isChake = false;
            do
            {
                isChake = false;
                analysisChars = SplitRecursionFunction(analysisChars, ref isChake);
            } while (isChake);

            Function function = ToFunction(analysisChars);

            return function;
        }

        /// <summary>
        /// 字符串转函数，返回判别条件对象
        /// </summary>
        /// <param name="str"></param>
        /// <param name="conditionItem"></param>
        /// <returns></returns>
        public Function StringToConditionFunction(string str, out ConditionItem conditionItem)
        {
            //string str = "sin(cos(aee,cee*d,(a+b)*c),a)";//sin(cos(aee,cee),eee+(fee*gee))*aee + sin(aee,bee)    sin(aooo,boo)*coo+boo  sin(cos(aee,cee*d,(a+b)*c),a)
            List<char> chars = str.ToList();

            AnalysisChars analysisChars = new AnalysisChars();
            for (int i = 0; i < chars.Count; i++)
            {
                if (chars[i] != ' ')
                {
                    analysisChars.subs.Add(new AnalysisChars(chars[i]));
                }
            }
            bool isChake = false;
            do
            {
                isChake = false;
                analysisChars = SplitRecursionFunction(analysisChars, ref isChake);
            } while (isChake);

            Function function = ToConditionFunction(analysisChars, out conditionItem);

            return function;
        }


        public Function StringToConditionReplaceFunction(string str, out ConditionItem conditionItem)
        {
            //string str = "sin(cos(aee,cee*d,(a+b)*c),a)";//sin(cos(aee,cee),eee+(fee*gee))*aee + sin(aee,bee)    sin(aooo,boo)*coo+boo  sin(cos(aee,cee*d,(a+b)*c),a)
            List<char> chars = str.ToList();

            AnalysisChars analysisChars = new AnalysisChars();
            for (int i = 0; i < chars.Count; i++)
            {
                if (chars[i] != ' ')
                {
                    analysisChars.subs.Add(new AnalysisChars(chars[i]));
                }
            }
            bool isChake = false;
            do
            {
                isChake = false;
                analysisChars = SplitRecursionFunction(analysisChars, ref isChake);
            } while (isChake);

            Function function = ToConditionFunction(analysisChars, out conditionItem);

            return function;
        }



        private Function ToFunction(AnalysisChars analysisChars)
        {
            Function function = null;
            switch (analysisChars.analysisType)
            {
                case AnalysisChars.AnalysisType.nil:
                    break;
                case AnalysisChars.AnalysisType.Char:
                    break;
                case AnalysisChars.AnalysisType.Name:
                    function = new Function(analysisChars.varName, algebraType);
                    break;
                case AnalysisChars.AnalysisType.BinaryOperator:
                    function = new Function(analysisChars.binaryOperatorFunctionType);
                    for (int i = 0; i < 2; i++)
                    {
                        function.SetArg(i, ToFunction(analysisChars.subs[i]));
                    }
                    break;
                case AnalysisChars.AnalysisType.Function:
                    function = new Function(analysisChars.functionType);
                    for (int i = 0; i < analysisChars.functionType.argCount; i++)
                    {
                        function.SetArg(i, ToFunction(analysisChars.subs[i]));
                    }
                    break;
                default:
                    break;
            }
            return function;
        }

        private Function ToConditionFunction(AnalysisChars analysisChars, out ConditionItem conditionItem)
        {
            Function function = null;
            conditionItem = null;
            switch (analysisChars.analysisType)
            {
                case AnalysisChars.AnalysisType.nil:
                    break;
                case AnalysisChars.AnalysisType.Char:
                    break;
                case AnalysisChars.AnalysisType.Name:
                    function = new ReplaceFunction(analysisChars.varName, algebraType);

                    conditionItem = new ConditionItem();
                    conditionItem.isVar = true;
                    conditionItem.type = algebraType;
                    conditionItem.varName = analysisChars.varName;

                    break;
                case AnalysisChars.AnalysisType.BinaryOperator:
                    function = new Function(analysisChars.binaryOperatorFunctionType);
                    conditionItem = new ConditionItem();
                    conditionItem.isVar = false;
                    conditionItem.isFunction = true;
                    conditionItem.type = analysisChars.binaryOperatorFunctionType;

                    for (int i = 0; i < 2; i++)
                    {
                        ConditionItem loopItemConditionItem;
                        function.SetArg(i, ToConditionFunction(analysisChars.subs[i], out loopItemConditionItem));
                        conditionItem.conditionItems[i] = loopItemConditionItem;
                    }
                    break;
                case AnalysisChars.AnalysisType.Function:
                    function = new Function(analysisChars.functionType);
                    conditionItem = new ConditionItem();
                    conditionItem.isVar = false;
                    conditionItem.isFunction = true;
                    conditionItem.type = analysisChars.binaryOperatorFunctionType;

                    for (int i = 0; i < analysisChars.functionType.argCount; i++)
                    {
                        ConditionItem loopItemConditionItem;
                        function.SetArg(i, ToConditionFunction(analysisChars.subs[i], out loopItemConditionItem));
                        conditionItem.conditionItems[i] = loopItemConditionItem;
                    }
                    break;
                default:
                    break;
            }
            return function;
        }

        private AnalysisChars SplitRecursionFunction(AnalysisChars func, ref bool isChake)
        {
            switch (func.analysisType)
            {
                case AnalysisChars.AnalysisType.nil:
                    func = SplitFunction(func);
                    isChake = true;
                    break;
                case AnalysisChars.AnalysisType.Char:
                    break;
                case AnalysisChars.AnalysisType.Name:
                    break;
                case AnalysisChars.AnalysisType.BinaryOperator:
                    //if (func.subs[0].analysisType == AnalysisChars.AnalysisType.nil)
                    //{
                    //}
                    //if (func.subs[1].analysisType == AnalysisChars.AnalysisType.nil)
                    //{
                    //}
                    func.subs[0] = SplitRecursionFunction(func.subs[0], ref isChake);
                    func.subs[1] = SplitRecursionFunction(func.subs[1], ref isChake);
                    break;
                case AnalysisChars.AnalysisType.Function:
                    for (int i = 0; i < func.subs.Count; i++)
                    {
                        func.subs[i] = SplitRecursionFunction(func.subs[i], ref isChake);
                    }
                    break;
                default:
                    break;
            }


            return func;

            //if (func is AnalysisChars)
            //{
            //    func = SplitFunction((AnalysisChars)func);
            //}
            //for (int i = 0; i < func.args.Length; i++)
            //{
            //    AnalysisChars analysisChars = func.args[i] as AnalysisChars;
            //    if (analysisChars != null && analysisChars.isChar == false)
            //    {
            //        func.args[i] = SplitRecursionFunction(analysisChars);
            //    }
            //}
            //return func;
        }

        private AnalysisChars SplitFunction(AnalysisChars analysisChars)
        {
            bool isBrackets = false;
            do
            {
                int startBrackets = -1;
                int endBrackets = analysisChars.subs.Count - 1;
                for (int i = 0; i < analysisChars.subs.Count; i++)
                {
                    var v = analysisChars.subs[i];
                    if (v.analysisType == AnalysisChars.AnalysisType.Char && v.n == '(')
                    {
                        startBrackets = i;
                        break;
                    }
                }
                isBrackets = false;
                int bracketsNumber = 1;
                if (startBrackets >= 0)
                {
                    isBrackets = true;
                    for (int i = startBrackets + 1; i < analysisChars.subs.Count; i++)
                    {
                        var v = analysisChars.subs[i];
                        if (v.analysisType == AnalysisChars.AnalysisType.Char)
                        {
                            if (v.n == '(')
                            {
                                bracketsNumber++;
                            }
                            else if (v.n == ')')
                            {
                                bracketsNumber--;
                            }
                            if (bracketsNumber == 0)
                            {
                                endBrackets = i;
                                break;
                            }
                        }
                    }

                    AnalysisChars analysisNew = new AnalysisChars();
                    for (int i = startBrackets + 1; i < endBrackets; i++)
                    {
                        analysisNew.subs.Add(analysisChars.subs[i]);
                    }
                    analysisChars.subs.RemoveRange(startBrackets, endBrackets - startBrackets + 1);

                    analysisChars.subs.Insert(startBrackets, analysisNew);
                }

            } while (isBrackets);

            return SplitBinaryOperator(analysisChars.subs);
        }

        AnalysisChars SplitBinaryOperator(List<AnalysisChars> analysisChars)
        {
            List<AnalysisChars> allVar = new List<AnalysisChars>();
            List<AnalysisChars> allBinaryOperator = new List<AnalysisChars>();

            int readStringIndex = 0;

            Loop:
            //string nowBinaryOperator = loop_c.ToString();
            for (int i = 0; i < analysisChars.Count; i++)
            {
                for (int indexBinaryOperator = 0; indexBinaryOperator < binaryOperatorFunctionTypes.Count; indexBinaryOperator++)
                {
                    var binaryOperatorName = binaryOperatorFunctionTypes[indexBinaryOperator].typeName;
                    if (analysisChars[i].analysisType != AnalysisChars.AnalysisType.Char)
                    {
                        continue;
                    }

                    if (binaryOperatorName[0] == analysisChars[i].n)
                    {
                        string nowBinaryOperator = analysisChars[i].n.ToString();
                        readStringIndex = i;
                        bool isLoopBinaryOperator = true;
                        for (readStringIndex++; readStringIndex < binaryOperatorName.Length + i; readStringIndex++)
                        {
                            if (analysisChars[readStringIndex].analysisType != AnalysisChars.AnalysisType.Char)
                            {
                                isLoopBinaryOperator = false;
                                break;
                            }
                            if (readStringIndex >= analysisChars.Count)
                            {
                                isLoopBinaryOperator = false;
                                break;
                            }
                            nowBinaryOperator += analysisChars[readStringIndex].n;
                            if (binaryOperatorName.IndexOf(nowBinaryOperator) != 0)
                            {
                                isLoopBinaryOperator = false;
                                break;
                            }
                        }

                        if (isLoopBinaryOperator)
                        {
                            AnalysisChars analysisCharsNew = new AnalysisChars();
                            for (int j = 0; j < i; j++)
                            {
                                analysisCharsNew.subs.Add(analysisChars[j]);
                            }
                            AnalysisChars binaryOperator = new AnalysisChars();
                            binaryOperator.binaryOperatorFunctionType = binaryOperatorFunctionTypes[indexBinaryOperator];
                            binaryOperator.analysisType = AnalysisChars.AnalysisType.BinaryOperator;

                            allVar.Add(analysisCharsNew);
                            allBinaryOperator.Add(binaryOperator);
                            //for (int j = i; j < readStringIndex; j++)
                            //{
                            //    analysisCharsNew.subs.Add(analysisChars[j]);
                            //}
                            analysisChars.RemoveRange(0, readStringIndex);

                            //isBinaryOperator = true;
                            goto Loop;
                        }
                    }
                }
            }


            AnalysisChars analysisCharsNew2 = new AnalysisChars();
            analysisCharsNew2.subs.AddRange(analysisChars);
            allVar.Add(analysisCharsNew2);


            List<AnalysisChars> allVarFunc = new List<AnalysisChars>();
            for (int i = 0; i < allVar.Count; i++)
            {
                bool isFunc = false;
                List<AnalysisChars> subs = allVar[i].subs;
                if (subs[subs.Count - 1].analysisType != AnalysisChars.AnalysisType.Char)
                {
                    StringBuilder sb = new StringBuilder();
                    for (int j = 0; j < subs.Count - 1; j++)
                    {
                        if (subs[j].analysisType == AnalysisChars.AnalysisType.Char)
                        {
                            sb.Append(subs[j].n);
                        }
                        else
                        {
                            goto endLoop;
                        }
                    }
                    for (int j = 0; j < functionTypes.Count; j++)
                    {
                        if (functionTypes[j].typeName == sb.ToString())
                        {
                            //Function function = new Function(functionTypes[j]);
                            //allVarFunc.Add(function);
                            //isFunc = true;

                            AnalysisChars function = new AnalysisChars();
                            function.functionType = functionTypes[j];
                            function.analysisType = AnalysisChars.AnalysisType.Function;


                            List<AnalysisChars> subs2 = subs[subs.Count - 1].subs;
                            List<AnalysisChars> allArg = new List<AnalysisChars>();
                            List<AnalysisChars> newArg = new List<AnalysisChars>();

                            int bracketsNumber = 0;
                            for (int k = 0; k < subs2.Count; k++)
                            {
                                var now = subs2[k];
                                switch (now.n)
                                {
                                    case '(':
                                        bracketsNumber++;
                                        newArg.Add(now);
                                        break;
                                    case ')':
                                        bracketsNumber--;
                                        newArg.Add(now);
                                        break;
                                    case ',':
                                        if (bracketsNumber == 0)
                                        {
                                            AnalysisChars analysis = new AnalysisChars();
                                            analysis.subs.AddRange(newArg);
                                            newArg.Clear();
                                            allArg.Add(analysis);
                                        }
                                        else
                                        {
                                            newArg.Add(now);
                                        }
                                        break;
                                    default:
                                        newArg.Add(now);
                                        break;
                                }
                            }

                            AnalysisChars analysis2 = new AnalysisChars();
                            analysis2.subs.AddRange(newArg);
                            allArg.Add(analysis2);

                            function.subs = allArg;


                            allVarFunc.Add(function);
                            isFunc = true;
                            break;
                        }
                    }
                    //
                }

                endLoop:
                if (!isFunc)
                {
                    AnalysisChars analysisChars2 = new AnalysisChars();
                    analysisChars2.analysisType = AnalysisChars.AnalysisType.Name;

                    StringBuilder sb = new StringBuilder();
                    for (int j = 0; j < subs.Count; j++)
                    {
                        if (subs[j].analysisType == AnalysisChars.AnalysisType.Char)
                        {
                            sb.Append(subs[j].n);
                        }
                        else
                        {
                            allVarFunc.Add(subs[j]);
                            goto endLoop2;
                        }
                    }
                    analysisChars2.varName = sb.ToString();
                    allVarFunc.Add(analysisChars2);
                }

                endLoop2:
                continue;
            }


            while (allBinaryOperator.Count > 0)
            {
                int big_priority = -1;
                int bigIndex = 0;
                for (int i = 0; i < allBinaryOperator.Count; i++)
                {
                    int priority = allBinaryOperator[i].binaryOperatorFunctionType.priority;
                    if (priority > big_priority)
                    {
                        bigIndex = i;
                        big_priority = priority;
                    }
                }

                AnalysisChars analysisTreeItem1 = allVarFunc[bigIndex];
                AnalysisChars analysisTreeItem2 = allVarFunc[bigIndex + 1];

                AnalysisChars analysisTreeItem = allBinaryOperator[bigIndex];
                analysisTreeItem.subs.Add(analysisTreeItem1);
                analysisTreeItem.subs.Add(analysisTreeItem2);

                allVarFunc[bigIndex] = analysisTreeItem;
                allVarFunc.RemoveAt(bigIndex + 1);
                allBinaryOperator.RemoveAt(bigIndex);

            }


            return allVarFunc[0];

        }

        Function AnalysisAlgebraObject(ReversePolishNotationExpressionStringItem item)
        {
            //GrammarAnalysisTree analysisTree = new GrammarAnalysisTree();

            List<Function> trees = new List<Function>();
            for (int i = 0; i < item.variables.Count; i++)
            {
                Function analysisTreeItem;
                if (item.variables[i].name == null)
                {
                    if (item.variables[i].fun == null)
                    {
                        analysisTreeItem = AnalysisAlgebraObject(item.variables[i]);
                    }
                    else
                    {
                        analysisTreeItem = item.variables[i].fun;
                        var list = item.variables[i].functionArgs;

                        for (int j = 0; j < list.Count; j++)
                        {
                            analysisTreeItem.SetArg(j, AnalysisAlgebraObject(list[j]));
                        }
                    }
                }
                else
                {
                    analysisTreeItem = new Function(item.variables[i].name, algebraType);
                    // new Function(item.variables[i].name, algebraTypel);
                    //analysisTreeItem.algebraObject = new Function(item.variables[i].name, algebraTypel);
                }
                trees.Add(analysisTreeItem);
            }

            while (item.binaryOperators.Count > 0)
            {
                int big_priority = -1;
                int bigIndex = 0;
                for (int i = 0; i < item.binaryOperators.Count; i++)
                {
                    int priority = (item.binaryOperators[i].funcType as BinaryOperatorFunctionType).priority;
                    if (priority > big_priority)
                    {
                        bigIndex = i;
                        big_priority = priority;
                    }
                }

                Function analysisTreeItem1 = trees[bigIndex];
                Function analysisTreeItem2 = trees[bigIndex + 1];

                Function analysisTreeItem = item.binaryOperators[bigIndex];
                analysisTreeItem.SetArg(0, analysisTreeItem1);
                analysisTreeItem.SetArg(1, analysisTreeItem2);

                trees[bigIndex] = analysisTreeItem;
                trees.RemoveAt(bigIndex + 1);
                item.binaryOperators.RemoveAt(bigIndex);
            }

            return trees[0];
        }

        /// <summary>
        /// 逆波兰符号表达式字符串对象
        /// </summary>
        class ReversePolishNotationExpressionStringItem
        {
            public List<ReversePolishNotationExpressionStringItem> variables = new List<ReversePolishNotationExpressionStringItem>();
            public List<Function> binaryOperators = new List<Function>();
            public List<ReversePolishNotationExpressionStringItem> functionArgs = new List<ReversePolishNotationExpressionStringItem>();
            public string name;
            public Function fun;
            public ReversePolishNotationExpressionStringItem(string name) { this.name = name; }
            public ReversePolishNotationExpressionStringItem(Function fun) { this.fun = fun; }
            public ReversePolishNotationExpressionStringItem() { }
        }

        ReversePolishNotationExpressionStringItem AnalysisItem(string infixExpression, ref int i)
        {
            ReversePolishNotationExpressionStringItem item = new ReversePolishNotationExpressionStringItem();
            string nowRead = "";
            string stringbinaryOperator;
            for (; i < infixExpression.Length; i++)
            {
                char loop_c = infixExpression[i];
                switch (loop_c)
                {
                    case '(':
                        i++;
                        item.variables.Add(AnalysisItem(infixExpression, ref i));
                        break;

                    case ')':
                    case ',':
                        // item.name = nowRead;
                        if (nowRead != "")
                        {
                            item.variables.Add(new ReversePolishNotationExpressionStringItem(nowRead));
                        }
                        return item;
                        break;

                    case ' ':
                        break;

                    default:
                        bool isBinaryOperator = false;
                        int indexBinaryOperator = 0;
                        int readStringIndex = i;
                        string nowBinaryOperator = loop_c.ToString();
                        for (; indexBinaryOperator < binaryOperatorFunctionTypes.Count; indexBinaryOperator++)
                        {
                            var binaryOperatorName = binaryOperatorFunctionTypes[indexBinaryOperator].typeName;
                            if (binaryOperatorName[0] == loop_c)
                            {
                                readStringIndex = i;
                                bool isLoopBinaryOperator = true;
                                for (readStringIndex++; readStringIndex < binaryOperatorName.Length + i; readStringIndex++)
                                {
                                    if (readStringIndex >= infixExpression.Length)
                                    {
                                        isLoopBinaryOperator = false;
                                        break;
                                    }
                                    nowBinaryOperator += infixExpression[readStringIndex];
                                    if (binaryOperatorName.IndexOf(nowBinaryOperator) != 0)
                                    {
                                        isLoopBinaryOperator = false;
                                        break;
                                    }
                                }

                                if (isLoopBinaryOperator)
                                {
                                    isBinaryOperator = true;
                                    break;
                                }
                            }
                        }


                        if (isBinaryOperator)
                        {
                            i = readStringIndex - 1;
                            //stringbinaryOperator = nowBinaryOperator;
                            item.binaryOperators.Add(new Function(binaryOperatorFunctionTypes[indexBinaryOperator]));
                            nowBinaryOperator = "";
                            if (nowRead != "")
                            {
                                item.variables.Add(new ReversePolishNotationExpressionStringItem(nowRead));
                            }
                            nowRead = "";
                        }
                        else
                        {
                            bool isFunction = false;
                            int indexFunction = 0;
                            readStringIndex = i;
                            string nowFunction = loop_c.ToString();
                            for (; indexFunction < functionTypes.Count; indexFunction++)
                            {
                                var functionName = functionTypes[indexFunction].typeName;
                                if (functionName[0] == loop_c)
                                {
                                    readStringIndex = i;
                                    bool isLoopFunction = true;
                                    for (readStringIndex++; readStringIndex < functionName.Length + i; readStringIndex++)
                                    {
                                        if (readStringIndex >= infixExpression.Length)
                                        {
                                            isLoopFunction = false;
                                            break;
                                        }
                                        nowFunction += infixExpression[readStringIndex];
                                        if (functionName.IndexOf(nowFunction) != 0)
                                        {
                                            isLoopFunction = false;
                                            break;
                                        }
                                    }

                                    if (isLoopFunction)
                                    {
                                        isFunction = true;
                                        break;
                                    }
                                }
                            }


                            if (isFunction)
                            {
                                var itemFunc = new Function(functionTypes[indexFunction]);
                                ReversePolishNotationExpressionStringItem itemV = new ReversePolishNotationExpressionStringItem(itemFunc);
                                for (; readStringIndex < infixExpression.Length; readStringIndex++)
                                {
                                    var loopChar = infixExpression[readStringIndex];
                                    switch (loopChar)
                                    {
                                        case ' ':

                                            break;
                                        case '(':
                                            readStringIndex++;
                                            itemV.functionArgs.Add(AnalysisItem(infixExpression, ref readStringIndex));
                                            if (infixExpression[readStringIndex - 1] == ')')
                                            {
                                                goto EndLoop;
                                            }
                                            break;
                                        //case ')':
                                        //    itemV.functionArgs.Add(new ReversePolishNotationExpressionStringItem(nowRead));
                                        //    goto EndLoop;
                                        //case ',':
                                        //    itemV.functionArgs.Add(new ReversePolishNotationExpressionStringItem(nowRead));
                                        //    break;
                                        default:
                                            itemV.functionArgs.Add(AnalysisItem(infixExpression, ref readStringIndex));
                                            //nowRead += loopChar;
                                            break;
                                    }
                                }
                                EndLoop:


                                //itemFunc.SetArgs(allArg);
                                //item.functions.Add(itemFunc);
                                item.variables.Add(itemV);
                                i = readStringIndex - 1;

                            }
                            else
                            {

                                nowRead += loop_c;
                            }
                        }
                        break;
                }
            }

            if (nowRead != "")
            {
                item.variables.Add(new ReversePolishNotationExpressionStringItem(nowRead));
            }
            // item.name = nowRead;

            return item;
        }
    }

    //public class AlgebraType
    //{
    //    public AlgebraType parentType { get; protected set; }
    //    public string typeName { get; protected set; }
    //    public AlgebraType(string typeName)
    //    {
    //        this.typeName = typeName;
    //        this.parentType = null;
    //    }

    //    public AlgebraType(string typeName, AlgebraType parentType)
    //    {
    //        this.typeName = typeName;
    //        this.parentType = parentType;
    //    }

    //}


    //public class AlgebraObject
    //{
    //    public string name { get; protected set; }
    //    public AlgebraType type { get; protected set; }
    //    public AlgebraObject(string name, AlgebraType type)
    //    {
    //        this.type = type;
    //        this.name = name;
    //    }
    //    public override string ToString()
    //    {
    //        return name;
    //    }
    //}

    public class FunctionType
    {
        public FunctionType parentType { get; protected set; }
        public string typeName { get; protected set; }
        public FunctionType(string typeName)
        {
            this.typeName = typeName;
            this.parentType = null;
        }

        public FunctionType(string typeName, FunctionType parentType)
        {
            this.typeName = typeName;
            this.parentType = parentType;
            this.returnType = parentType;
            _isAbstract = true;
        }

        protected FunctionType[] argTypes = new FunctionType[0];
        protected FunctionType returnType;
        bool _isAbstract = false;

        public bool isAbstract { get { return _isAbstract; } }

        public virtual int argCount { get { return argTypes.Length; } }

        public FunctionType(string typeName, IList<FunctionType> algebraTypes, FunctionType returnType, FunctionType parentType)
            : this(typeName, parentType)
        {
            argTypes = new FunctionType[algebraTypes.Count];
            Array.Copy(algebraTypes.ToArray(), argTypes, algebraTypes.Count);
        }

        public virtual string GetToString(Function function)
        {
            if (function.funcType.argCount > 0)
            {
                StringBuilder bs = new StringBuilder();
                bs.Append(function.name + "(");
                for (int i = 0; i < function.funcType.argCount - 1; i++)
                {
                    bs.Append(function[i].ToString() + ",");
                }
                bs.Append(function[function.funcType.argCount - 1].ToString() + ")");
                return bs.ToString();
            }
            return function.name;
        }
    }

    /// <summary>
    /// 替代函数 用于代数运算替换
    /// </summary>
    public class ReplaceFunction : Function
    {
        public ReplaceFunction(string name, FunctionType functionType)
            : base(name, functionType)
        {

        }

        public override Function Copy()
        {
            ReplaceFunction function = new ReplaceFunction(this.name, this.funcType);
            function._isComplete = this._isComplete;
            for (int i = 0; i < args.Length; i++)
            {
                if (args[i] != null)
                {
                    function.SetArg(i, args[i].Copy());
                }
            }
            return function;
        }

    }

    /// <summary>
    /// 函数，所有变换、变量都是函数， 单个变量只是返回自己的函数
    /// </summary>
    public class Function
    {
        public Function this[int index]
        {
            get { return args[index]; }
        }

        public IReadOnlyList<Function> Args
        {
            get { return args; }
        }

        protected Function[] args;
        public bool _isComplete;
        /// <summary>
        /// 是否所有参数 
        /// </summary>
        public bool isComplete { get { return _isComplete; } }
        public int ArgLength { get { return args.Length; } }

        public string name { get; protected set; }
        public FunctionType funcType { get; protected set; }
        public Type getType { get { return this.GetType(); } }

        public Function(string name, FunctionType functionType)
        {
            this.funcType = functionType;
            this.name = name;
            args = new Function[functionType.argCount];
        }
        public Function(FunctionType functionType)
        {
            this.name = functionType.typeName;
            _isComplete = false;
            this.funcType = functionType;
            args = new Function[functionType.argCount];
        }

        public void SetArg(int index, Function algebraObject)
        {
            args[index] = algebraObject;
            ChakeArgs();
        }

        public void SetArgs(IList<Function> algebraObjects)
        {
            for (int i = 0; i < algebraObjects.Count; i++)
            {
                args[i] = algebraObjects[i];
            }
            ChakeArgs();
        }

        void ChakeArgs()
        {
            for (int i = 0; i < args.Length; i++)
            {
                if (args[i] == null)
                {
                    return;
                }
            }
            _isComplete = true;
        }

        /// <summary>
        /// 深拷贝
        /// </summary>
        /// <returns></returns>
        public virtual Function Copy()
        {
            Function function = new Function(this.name, this.funcType);
            function._isComplete = this._isComplete;
            for (int i = 0; i < args.Length; i++)
            {
                if (args[i] != null)
                {
                    function.SetArg(i, args[i].Copy());
                }
            }
            return function;
        }

        /// <summary>
        /// 这个拷贝函数 太他妈坑比了 暂时不用了
        /// </summary>
        /// <param name="getThis1"></param>
        /// <param name="getThis2"></param>
        /// <param name="newThis1"></param>
        /// <param name="newThis2"></param>
        /// <returns></returns>
        public virtual Function Copy(Function getThis1, Function getThis2, ref Function newThis1, ref Function newThis2)
        {
            Function function = new Function(this.name, this.funcType);
            if (this == getThis1)
            {
                newThis1 = function;
            }
            if (this == getThis2)
            {
                newThis2 = function;
            }
            function._isComplete = this._isComplete;
            for (int i = 0; i < args.Length; i++)
            {
                if (args[i] != null)
                {
                    function.SetArg(i, args[i].Copy(getThis1, getThis2, ref newThis1, ref newThis2));
                    if (args[i] == getThis1)
                    {
                        newThis1 = function[i];
                    }
                    if (args[i] == getThis2)
                    {
                        newThis2 = function[i];
                    }
                }
            }

            return function;
        }

        public virtual bool CompareName(Function function)
        {
            return function.name == this.name;
        }

        public override string ToString()
        {
            return funcType.GetToString(this);
        }
        public string GetToString { get { return ToString(); } }
    }

    /// <summary>
    /// 二目表达式
    /// </summary>
    public class BinaryOperatorFunctionType : FunctionType
    {
        int _priority;
        public virtual int priority { get { return _priority; } }
        public virtual FunctionType leftAlgebraType { get { return argTypes[0]; } set { argTypes[0] = value; } }
        public virtual FunctionType rightAlgebraType { get { return argTypes[1]; } set { argTypes[1] = value; } }
        public override int argCount { get { return 2; } }

        public BinaryOperatorFunctionType(string typeName, int priority, FunctionType leftAlgebraType, FunctionType rightAlgebraType, FunctionType returnType, FunctionType parentType)
            : base(typeName, parentType)
        {
            argTypes = new FunctionType[2];
            argTypes[0] = leftAlgebraType;
            argTypes[1] = rightAlgebraType;
            this.returnType = returnType;
            this._priority = priority;
        }

        public override string GetToString(Function function)
        {
            StringBuilder sb = new StringBuilder();
            if (function.isComplete)
            {
                if (function[0].funcType is BinaryOperatorFunctionType && (function[0].funcType as BinaryOperatorFunctionType).priority < this.priority)
                {
                    sb.Append("(" + function[0].ToString() + ")");
                }
                else
                {
                    sb.Append(function[0].ToString());
                }
                sb.Append(typeName);
                if (function[1].funcType is BinaryOperatorFunctionType && (function[1].funcType as BinaryOperatorFunctionType).priority <= this.priority)
                {
                    sb.Append("(" + function[1].ToString() + ")");
                }
                else
                {
                    sb.Append(function[1].ToString());
                }
                return sb.ToString();
            }
            return typeName;
        }
    }




}
